package com.gitee.wsl.transform.converter

import com.gitee.wsl.func.Function
import com.gitee.wsl.func.InvokeCall

fun interface Converter<A, B>: InvokeCall<A, B> {
    fun convert(a: A): B

    override operator fun invoke(t: A) = convert(t)

    companion object
}

typealias StringConverter =  Converter<String,String>

interface ReverseAbleConverter<A, B>:Converter<A, B>{
    fun reverseConverter(): ReverseAbleConverter<B, A>

    fun reverse(b:B):A

    fun convertAll(fromIterable: Iterable<A>): Iterable<B>
}

/**
 * A function from `A` to `B` with an associated *reverse* function from `B`
 * to `A`; used for converting back and forth between *different representations of the same
 * information*.
 *
 * <h3>Invertibility</h3>
 *
 *
 * The reverse operation **may** be a strict *inverse* (meaning that `converter.reverse().convert(converter.convert(a)).equals(a)` is always true). However, it is very
 * common (perhaps *more* common) for round-trip conversion to be *lossy*. Consider an
 * example round-trip using [com.google.common.primitives.Doubles.stringConverter]:
 *
 *
 *  1. `stringConverter().convert("1.00")` returns the `Double` value `1.0`
 *  1. `stringConverter().reverse().convert(1.0)` returns the string `"1.0"` --
 * *not* the same string (`"1.00"`) we started with
 *
 *
 *
 * Note that it should still be the case that the round-tripped and original objects are
 * *similar*.
 *
 * <h3>Nullability</h3>
 *
 *
 * A converter always converts `null` to `null` and non-null references to non-null
 * references. It would not make sense to consider `null` and a non-null reference to be
 * "different representations of the same information", since one is distinguishable from
 * *missing* information and the other is not. The [.convert] method handles this null
 * behavior for all converters; implementations of [.doForward] and [.doBackward] are
 * guaranteed to never be passed `null`, and must never return `null`.
 *
 * <h3>Common ways to use</h3>
 *
 *
 * Getting a converter:
 *
 *
 *  * Use a provided converter implementation, such as [Enums.stringConverter], [       ][com.google.common.primitives.Ints.stringConverter] or the [       ][.reverse] views of these.
 *  * Convert between specific preset values using [       ][com.google.common.collect.Maps.asConverter]. For example, use this to
 * create a "fake" converter for a unit test. It is unnecessary (and confusing) to *mock*
 * the `Converter` type using a mocking framework.
 *  * Extend this class and implement its [.doForward] and [.doBackward] methods.
 *  * **Java 8 users:** you may prefer to pass two lambda expressions or method references to
 * the [from][.from] factory method.
 *
 *
 *
 * Using a converter:
 *
 *
 *  * Convert one instance in the "forward" direction using `converter.convert(a)`.
 *  * Convert multiple instances "forward" using `converter.convertAll(as)`.
 *  * Convert in the "backward" direction using `converter.reverse().convert(b)` or `converter.reverse().convertAll(bs)`.
 *  * Use `converter` or `converter.reverse()` anywhere a [       ] is accepted (for example [       Stream.map][java.util.stream.Stream.map]).
 *  * **Do not** call [.doForward] or [.doBackward] directly; these exist only to
 * be overridden.
 *
 *
 * <h3>Example</h3>
 *
 * <pre>
 * return new Converter&lt;Integer, String&gt;() {
 * protected String doForward(Integer i) {
 * return Integer.toHexString(i);
 * }
 *
 * protected Integer doBackward(String s) {
 * return parseUnsignedInt(s, 16);
 * }
 * };</pre>
 *
 *
 * An alternative using Java 8:
 *
 * <pre>`return Converter.from(
 * Integer::toHexString,
 * s -> parseUnsignedInt(s, 16));
`</pre> *
 *
 * @author Mike Ward
 * @author Kurt Alfred Kluever
 * @author Gregory Kick
 * @since 16.0
 */
/*
 * 1. The type parameter is <T> rather than <T extends @Nullable> so that we can use T in the
 * doForward and doBackward methods to indicate that the parameter cannot be null. (We also take
 * advantage of that for convertAll, as discussed on that method.)
 *
 * 2. The supertype of this class could be `Function<@Nullable A, @Nullable B>`, since
 * Converter.apply (like Converter.convert) is capable of accepting null inputs. However, a
 * supertype of `Function<A, B>` turns out to be massively more useful to callers in practice: They
 * want their output to be non-null in operations like `stream.map(myConverter)`, and we can
 * guarantee that as long as we also require the input type to be non-null[*] (which is a
 * requirement that existing callers already fulfill).
 *
 * Disclaimer: Part of the reason that callers are so well adapted to `Function<A, B>` may be that
 * that is how the signature looked even prior to this comment! So naturally any change can break
 * existing users, but it can't *fix* existing users because any users who needed
 * `Function<@Nullable A, @Nullable B>` already had to find a workaround. Still, there is a *ton* of
 * fallout from trying to switch. I would be shocked if the switch would offer benefits to anywhere
 * near enough users to justify the costs.
 *
 * Fortunately, if anyone does want to use a Converter as a `Function<@Nullable A, @Nullable B>`,
 * it's easy to get one: `converter::convert`.
 *
 * [*] In annotating this class, we're ignoring LegacyConverter.
 */
abstract class AbstractConverter<A, B>(private val handleNullAutomatically: Boolean):
    ReverseAbleConverter<A, B> {
    // We lazily cache the reverse view to avoid allocating on every call to reverse().
    private var reverse: AbstractConverter<B, A>? = null

    /** Constructor for use by subclasses.  */
    protected constructor() : this(true)
    // SPI methods (what subclasses must implement)
    /**
     * Returns a representation of `a` as an instance of type `B`. If `a` cannot be
     * converted, an unchecked exception (such as [IllegalArgumentException]) should be thrown.
     *
     * @param a the instance to convert; will never be null
     * @return the converted instance; **must not** be null
     */
    protected abstract fun doForward(a: A): B

    /**
     * Returns a representation of `b` as an instance of type `A`. If `b` cannot be
     * converted, an unchecked exception (such as [IllegalArgumentException]) should be thrown.
     *
     * @param b the instance to convert; will never be null
     * @return the converted instance; **must not** be null
     * @throws UnsupportedOperationException if backward conversion is not implemented; this should be
     * very rare. Note that if backward conversion is not only unimplemented but
     * unimplement*able* (for example, consider a `Converter<Chicken, ChickenNugget>`),
     * then this is not logically a `Converter` at all, and should just implement [     ].
     */
   
    protected abstract fun doBackward(b: B): A
    // API (consumer-side) methods
    /**
     * Returns a representation of `a` as an instance of type `B`.
     *
     * @return the converted value; is null *if and only if* `a` is null
     */

    override fun convert(a: A): B {
        return correctedDoForward(a)
    }

    override fun reverse(b: B): A {
        return correctedDoBackward(b)
    }

    open fun correctedDoForward(a: A): B {
        return if (handleNullAutomatically) {
            // TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
            doForward(a)
        } else {
            unsafeDoForward(a)
        }
    }

   
    open fun correctedDoBackward(b: B): A {
        return if (handleNullAutomatically) {
            // TODO(kevinb): we shouldn't be checking for a null result at runtime. Assert?
           doBackward(b)
        } else {
            unsafeDoBackward(b)
        }
    }

    /*
   * LegacyConverter violates the contract of Converter by allowing its doForward and doBackward
   * methods to accept null. We could avoid having unchecked casts in Converter.java itself if we
   * could perform a cast to LegacyConverter, but we can't because it's an internal-only class.
   *
   * TODO(cpovirk): So make it part of the open-source build, albeit package-private there?
   *
   * So we use uncheckedCastNullableTToT here. This is a weird usage of that method: The method is
   * documented as being for use with type parameters that have parametric nullness. But Converter's
   * type parameters do not. Still, we use it here so that we can suppress a warning at a smaller
   * level than the whole method but without performing a runtime null check. That way, we can still
   * pass null inputs to LegacyConverter, and it can violate the contract of Converter.
   *
   * TODO(cpovirk): Could this be simplified if we modified implementations of LegacyConverter to
   * override methods (probably called "unsafeDoForward" and "unsafeDoBackward") with the same
   * signatures as the methods below, rather than overriding the same doForward and doBackward
   * methods as implementations of normal converters do?
   *
   * But no matter what we do, it's worth remembering that the resulting code is going to be unsound
   * in the presence of LegacyConverter, at least in the case of users who view the converter as a
   * Function<A, B> or who call convertAll (and for any checkers that apply @PolyNull-like semantics
   * to Converter.convert). So maybe we don't want to think too hard about how to prevent our
   * checkers from issuing errors related to LegacyConverter, since it turns out that
   * LegacyConverter does violate the assumptions we make elsewhere.
   */
    
    private fun unsafeDoForward( a: A): B {
        return doForward(a)
    }

    private fun unsafeDoBackward( b: B): A {
        return doBackward(b)
    }

    /**
     * Returns an iterable that applies `convert` to each element of `fromIterable`. The
     * conversion is done lazily.
     *
     *
     * The returned iterable's iterator supports `remove()` if the input iterator does. After
     * a successful `remove()` call, `fromIterable` no longer contains the corresponding
     * element.
     */
    /*
   * Just as Converter could implement `Function<@Nullable A, @Nullable B>` instead of `Function<A,
   * B>`, convertAll could accept and return iterables with nullable element types. In both cases,
   * we've chosen to instead use a signature that benefits existing users -- and is still safe.
   *
   * For convertAll, I haven't looked as closely at *how* much existing users benefit, so we should
   * keep an eye out for problems that new users encounter. Note also that convertAll could support
   * both use cases by using @PolyNull. (By contrast, we can't use @PolyNull for our superinterface
   * (`implements Function<@PolyNull A, @PolyNull B>`), at least as far as I know.)
   */
    override fun convertAll(fromIterable: Iterable<A>): Iterable<B> {
        return object : Iterable<B> {
            override fun iterator(): Iterator<B> {
                return object : Iterator<B> {
                    private val fromIterator = fromIterable.iterator()
                    override fun hasNext(): Boolean {
                        return fromIterator.hasNext()
                    }

                    override fun next(): B {
                        return convert(fromIterator.next())
                    }
                }
            }
        }
    }

    /**
     * Returns the reversed view of this converter, which converts `this.convert(a)` back to a
     * value roughly equivalent to `a`.
     *
     *
     * The returned converter is serializable if `this` converter is.
     *
     *
     * **Note:** you should not override this method. It is non-final for legacy reasons.
     */

    override fun reverseConverter(): AbstractConverter<B, A> {
        val result = reverse
        return result ?: ReverseConverter(this).also {
                reverse = it
            }
    }

    private class ReverseConverter<A, B> (val original: AbstractConverter<A, B>) : AbstractConverter<B, A>() {
        /*
    * These gymnastics are a little confusing. Basically this class has neither legacy nor
    * non-legacy behavior; it just needs to let the behavior of the backing converter shine
    * through. So, we override the correctedDo* methods, after which the do* methods should never
    * be reached.
    */
        override fun doForward(b: B): A {
            throw AssertionError()
        }

        override fun doBackward(a: A): B {
            throw AssertionError()
        }

        
        override fun correctedDoForward( b: B): A {
            return original.correctedDoBackward(b)
        }

        
        override fun correctedDoBackward( a: A): B {
            return original.correctedDoForward(a)
        }

        override fun reverseConverter(): AbstractConverter<A, B> {
            return original
        }

        override fun equals( `object`: Any?): Boolean {
            if (`object` is ReverseConverter<*, *>) {
                return original == `object`.original
            }
            return false
        }

        override fun hashCode(): Int {
            return original.hashCode().inv()
        }

        override fun toString(): String {
            return "$original.reverse()"
        }

    }

    /**
     * Returns a converter whose `convert` method applies `secondConverter` to the result
     * of this converter. Its `reverse` method applies the converters in reverse order.
     *
     *
     * The returned converter is serializable if `this` converter and `secondConverter`
     * are.
     */
    fun <C> andThen(secondConverter: AbstractConverter<B, C>): AbstractConverter<A, C> {
        return doAndThen(secondConverter)
    }

    /** Package-private non-final implementation of andThen() so only we can override it.  */
    open fun <C> doAndThen(secondConverter: AbstractConverter<B, C>): AbstractConverter<A, C> {
        return ConverterComposition(this, secondConverter)
    }

    private class ConverterComposition<A, B, C> (
        val first: AbstractConverter<A, B>,
        val second: AbstractConverter<B, C>
    ) : AbstractConverter<A, C>(){
        /*
    * These gymnastics are a little confusing. Basically this class has neither legacy nor
    * non-legacy behavior; it just needs to let the behaviors of the backing converters shine
    * through (which might even differ from each other!). So, we override the correctedDo* methods,
    * after which the do* methods should never be reached.
    */
        override fun doForward(a: A): C {
            throw AssertionError()
        }

        override fun doBackward(c: C): A {
            throw AssertionError()
        }

        
        override fun correctedDoForward( a: A): C {
            return second.correctedDoForward(first.correctedDoForward(a))
        }

        
        override fun correctedDoBackward( c: C): A {
            return first.correctedDoBackward(second.correctedDoBackward(c))
        }

        override fun equals( `object`: Any?): Boolean {
            if (`object` is ConverterComposition<*, *, *>) {
                val that = `object`
                return first == that.first && second == that.second
            }
            return false
        }

        override fun hashCode(): Int {
            return 31 * first.hashCode() + second.hashCode()
        }

        override fun toString(): String {
            return "$first.andThen($second)"
        }

    }


    /**
     * Indicates whether another object is equal to this converter.
     *
     *
     * Most implementations will have no reason to override the behavior of [Object.equals].
     * However, an implementation may also choose to return `true` whenever `object` is a
     * [AbstractConverter] that it considers *interchangeable* with this one. "Interchangeable"
     * *typically* means that `Objects.equal(this.convert(a), that.convert(a))` is true for
     * all `a` of type `A` (and similarly for `reverse`). Note that a `false`
     * result from this method does not imply that the converters are known *not* to be
     * interchangeable.
     */
    override fun equals( `object`: Any?): Boolean {
        return super.equals(`object`)
    }

    override fun hashCode(): Int {
        var result = handleNullAutomatically.hashCode()
        result = 31 * result + (reverse?.hashCode() ?: 0)
        return result
    }

    private class FunctionBasedConverter<A, B>(
        private val forwardFunction: Function<in A, out B>,
        private val backwardFunction: Function<in B, out A>
    ) : AbstractConverter<A, B>() {
        override fun doForward(a: A): B {
            return forwardFunction.apply(a)
        }

        override fun doBackward(b: B): A {
            return backwardFunction.apply(b)
        }

        override fun equals( `object`: Any?): Boolean {
            if (`object` is FunctionBasedConverter<*, *>) {
                val that = `object`
                return (forwardFunction == that.forwardFunction && backwardFunction == that.backwardFunction)
            }
            return false
        }

        override fun hashCode(): Int {
            return forwardFunction.hashCode() * 31 + backwardFunction.hashCode()
        }

        override fun toString(): String {
            return "Converter.from($forwardFunction, $backwardFunction)"
        }
    }

    /**
     * A converter that always converts or reverses an object to itself. Note that T is now a
     * "pass-through type".
     */
    private class IdentityConverter<T>(): AbstractConverter<T, T>() {
        override fun doForward(a: T): T {
            return a
        }

        override fun doBackward(b: T): T {
            return b
        }

        override fun reverseConverter(): AbstractConverter<T, T> {
            return this
        }

        override fun <S> doAndThen(secondConverter: AbstractConverter<T, S>): AbstractConverter<T, S> {
            return secondConverter
        }

        /*
     * We *could* override convertAll() to return its input, but it's a rather pointless
     * optimization and opened up a weird type-safety problem.
     */
        override fun toString(): String {
            return "Converter.identity()"
        }

        private fun readResolve(): Any {
            return INSTANCE
        }

        companion object {
            val INSTANCE: AbstractConverter<*, *> = IdentityConverter<Any>()
        }
    }

    companion object {
        // Static converters
        /**
         * Returns a converter based on separate forward and backward functions. This is useful if the
         * function instances already exist, or so that you can supply lambda expressions. If those
         * circumstances don't apply, you probably don't need to use this; subclass `Converter` and
         * implement its [.doForward] and [.doBackward] methods directly.
         *
         *
         * These functions will never be passed `null` and must not under any circumstances
         * return `null`. If a value cannot be converted, the function should throw an unchecked
         * exception (typically, but not necessarily, [IllegalArgumentException]).
         *
         *
         * The returned converter is serializable if both provided functions are.
         *
         * @since 17.0
         */
        fun <A, B> from(
            forwardFunction: Function<in A, out B>,
            backwardFunction: Function<in B, out A>
        ): AbstractConverter<A, B> {
            return FunctionBasedConverter(forwardFunction, backwardFunction)
        }

        /** Returns a serializable converter that always converts or reverses an object to itself.  */
        // implementation is "fully variant"
        fun identity(): AbstractConverter<*, *> {
            return IdentityConverter.INSTANCE
        }
    }
}

//fun String.convert(converter:StringConverter) = converter.convert(this)

fun <A,B> A.convert(converter: Converter<A,B>) = converter.convert(this)

fun <A,B> B.reverse(converter: ReverseAbleConverter<A,B>) = converter.reverse(this)
